#ifndef SPL_FRAMEWND
#define SPL_FRAMEWND

//! Modal dialog result
enum DialogResult
{
  DialogError,
  DialogCancel,
  DialogOK,
};

class DLLEXPORT FrameWnd : public WndBase
{
private:
#pragma region Internal Classes
  //! Class to handle drag drop output
  class DropSource;
  //! Class to handle drag drop input
  class DropTarget;
#pragma endregion

#pragma region Internal Declarations
  //! Window drag drop target
  DropTarget*   mDropTarget;
  //! Mouse is over window
  BOOL          mIsMouseOver;
  //! Window is shown modally
  BOOL          mModal;
  //! Dialog result
  DialogResult  mResult;
#pragma endregion

protected:
#pragma region Protected Methods
  //! Window specific procedure
  //! msg:		             message code
  //! wParam:		           message's wParam
  //! lParam:		           message's lParam
  //! lResult:             message result
  //! handled:             true if the message is handled
  virtual VOID wndProc(Event::WndProcEvent& iEvent);
#pragma endregion

#pragma region Control Notifications
  //! Occurs when the visual aspect of a child control has changed
  //! id:                  control identifier, 0 if menu item
  //! drawStruct:          item drawing structure
  virtual VOID onDrawItem(Event::DrawItemEvent& iEvent);

  //! Occurs when a child control is created
  //! id:                  control identifier, 0 if menu item
  //! measureStruct:       item measuring structure
  virtual VOID onMeasureItem(Event::MeasureItemEvent& iEvent);

  //! Occurs when a sorted item of a child control needs to be positionned
  //! id:                  control identifier, 0 if menu item
  //! compareStruct:       item comparing structure
  //! Returns:             -1 if before, 0 if same position, 1 if after
  //!                      (in relation with item 2)
  virtual VOID onCompareItem(Event::CompareItemEvent& iEvent);

  //! Occurs when a child window needs so send or retrieve some information
  //! id:                  control identifier, 0 if menu item
  //! drawStruct:          item drawing structure
  virtual VOID onNotify(Event::NotifyEvent& iEvent);
#pragma endregion

#pragma region Menu Notifications
  //! Occurs when the user clicks the right mouse button in a window
  //! hWnd:                window handle
  //! x:                   horizontal screen coordinate of the cursor
  //! y:                   vertical screen coordinate of the cursor
  virtual VOID onContextMenu(Event::ContextMenuEvent& iEvent);

  //! Occurs when the user makes a selection from a menu
  //! itemIndex:           zero-based index of the selected item
  //! hMenu:               menu handle
  virtual VOID onMenuCommand(Event::MenuCommandEvent& iEvent);
#pragma endregion

#pragma region Mouse Notifications
  //! Occurs when the mouse enters the window
  virtual VOID onMouseEnter(Event::MouseEvent& iEvent);

  //! Occurs when the mouse has moved
  virtual VOID onMouseMove(Event::MouseEvent& iEvent);

  //! Occurs when the mouse leaves the window client area
  virtual VOID onMouseLeave();

  //! Occurs when a mouse button is pressed
  virtual VOID onMouseDown(Event::MouseEvent& iEvent);

  //! Occurs when a mouse button is released
  virtual VOID onMouseUp(Event::MouseEvent& iEvent);

  //! Occurs when the mouse wheel is rotated
  virtual VOID onMouseWheel(Event::MouseWheelEvent& iEvent);

  //! Occurs when the left mouse button is pressed within
  //! the nonclient area of the window
  virtual VOID onNCMouseDown(Event::MouseEvent& iEvent);

  //! Occurs when the left mouse button is released within
  //! the nonclient area of the window
  virtual VOID onNCMouseUp(Event::MouseEvent& iEvent);

  //! Determines which part of the window corresponds to a particular
  //! screen coordinate
  //! nX:              cursor horizontal coordinate
  //! nY:              cursor vertical coordinate
  //! Result:          any HT* value
  virtual VOID onNCHitTest(Event::NCHitTestEvent& iEvent);
#pragma endregion

#pragma region Painting & Drawing Notifications
  // http://msdn.microsoft.com/en-us/library/dd162761%28v=VS.85%29.aspx
  // unimplemented:
  //      WM_ICONERASEBKGND, WM_PAINTICON

  //! Occurs when the window client area must be painted
  virtual VOID onPaint();

  //! Occurs when the window frame must be painted
  //! hUpdateRgn:          handle to the update region
  virtual VOID onNCPaint(Event::NCPaintEvent& iEvent);

  //! Occurs when the window background must be cleared
  //! hDeviceContext:      handle to the device context
  //! Returns:
  //!          false to cancel the operation, true to continue
  virtual VOID onEraseBackground(Event::EraseBackgroundEvent& iEvent);

#ifndef COMMON_WM_ONLY
  //! Occurs when a window must be drawn on a specific device context
  //! (mostly a printer device context)
  //! hDeviceContext:      handle to the device context
  //! nDrawingOpt:         drawing options (any PRF_* value)
  virtual VOID onPrint(Event::PrintEvent& iEvent);

  //! Occurs when a window client area must be drawn on a
  //! specific device context (mostly a printer device context)
  //! hDeviceContext:      handle to the device context
  //! nDrawingOpt:         drawing options (any PRF_* value)
  virtual VOID onPrintClient(Event::PrintEvent& iEvent);

  //! Occurs when window must be redrawn or prevented from painting
  //! bRedraw:             true if the window must be drawn
  //!                      false if the window must not be drawn
  virtual VOID onSetRedraw(Event::SetRedrawEvent& iEvent);

  //! Occurs when a window painting must be synchronized with
  //! another window
  virtual VOID onSyncPaint();
#endif
#pragma endregion

#pragma region Keyboard Notifications
  // http://msdn.microsoft.com/en-us/library/ff468861%28v=VS.85%29.aspx

  //! Occurs when the window is activated or deactivated
  //! nWindowState:    window state of the window (any WA_* value)
  //! bMinimized:      the window is minimized
  //! hWnd:            window handle of the other window
  virtual VOID onActivate(Event::ActivateEvent& iEvent);

  //! Occurs when a non-system key is pressed
  //! keyData:         informations on key message
  virtual VOID onKeyDown(Event::KeyEvent& iEvent);

  //! Occurs when a non-system key is released
  //! keyData:         informations on key message
  virtual VOID onKeyUp(Event::KeyEvent& iEvent);

  //! Occurs when a system key is pressed
  //! keyData:         informations on key message
  virtual VOID onSysKeyDown(Event::KeyEvent& iEvent);

  //! Occurs when a system key is released
  //! keyData:         informations on key message
  virtual VOID onSysKeyUp(Event::KeyEvent& iEvent);

  //! Occurs when a window gets the keyboard focus
  //! hWnd:            handle of the window receiving focus
  virtual VOID onSetFocus(Event::FocusEvent& iEvent);

  //! Occurs when a window loses the keyboard focus
  //! hWnd:            handle of the window losing focus
  virtual VOID onKillFocus(Event::FocusEvent& iEvent);
#pragma endregion

#pragma region Scroll Bar Notifications
  //! Occurs for each child horizontal scrollbar event
  virtual VOID onHScroll(Event::ScrollEvent& iEvent);

  //! Occurs for each child vertical scrollbar event
  virtual VOID onVScroll(Event::ScrollEvent& iEvent);
#pragma endregion

#pragma region Window Notifications
  // http://msdn.microsoft.com/en-us/library/ff468922%28v=VS.85%29.aspx
  // unimplemented:
  //      WM_CANCELMODE, WM_CHILDACTIVATE, WM_COMPACTING,
  //      WM_INPUTLANGCHANGE, WM_INPUTLANGCHANGEREQUEST,
  //      WM_NCCREATE, WM_NCDESTROY

  //! Occurs when a window is about to be hidden or shown
  //! bShown:          the window is being shown
  //! nStatus:         the status of the window (any SW_* value)
  virtual VOID onShowWindow(Event::ShowWindowEvent& iEvent);

#ifndef COMMON_WM_ONLY
  //! Occurs when the window is requested to restore
  //! Returns:         true if the window can be opened
  virtual VOID onQueryOpen(Event::QueryEvent& iEvent);

  //! Occurs when a minimized window is about to be dragged but
  //! does not have any icon defined
  //! Returns:         handle to an icon or cursor to display during
  //!                  the drag or NULL to display the default cursor
  virtual VOID onQueryDragIcon(Event::QueryDragIconEvent& iEvent);

  //! Occurs when then window is being resized or moved
  virtual VOID onEnterSizeMove();

  //! Occurs when then window was resized or moved
  virtual VOID onExitSizeMove();

  //! Occurs when the window icon is requested
  //! nIconType:       type of the icon to retrieve
  //!                  can be ICON_BIG, ICON_SMALL or ICON_SMALL2
  //! Returns:         handle to the window icon
  virtual VOID onGetIcon(Event::GetIconEvent& iEvent);
#endif

  //! Occurs when calculating client and non-client areas
  //! fUpdate:         the application should indicate which part of the
  //!                  client area contains valid information
  //! pStruct:         if fUpdate, NCCALCSIZE_PARAMS, otherwise RECT
  virtual VOID onNCCalcSize(Event::NCCalcSizeEvent& iEvent);

  //! Occurs when a child window is clicked, created or destroyed
  //! childMsg:        the message received by the child window
  //! msgData:         if childMsg is WM_CREATE or WM_DESTROY,
  //!                  identifier of the child window
  //!                  if childMsg is WM_XBUTTONDOWN,
  //!                  corresponds to XBUTTON1 or XBUTTON2
  //! lParam:          if childMsg is WM_CREATE or WM_DESTROY,
  //!                  contains the handle of the child window
  //!                  if childMSg is a mouse event message,
  //!                  the low-word is the x and the high-word the y
  //!                  coordinate of the mouse
  virtual VOID onParentNotify(Event::ParentNotifyEvent& iEvent);

  //! Occurs when an application is losing focus to this window or
  //! this window is giving focus to another application
  //! bWndActivated:   the application is being activated
  //! dwThread:        application thread identifier
  virtual VOID onActivateApp(Event::ActivateAppEvent& iEvent);

  //! Occurs when the window is about to be sized or moved
  //! pMinMaxInfo:     pointer to a MINMAXINFO structure
  virtual VOID onGetMinMaxInfo(Event::MinMaxInfoEvent& iEvent);

  //! Occurs after the window position or order has changed
  //! pWindowPos:      pointer to a WINDOWPOS structure
  virtual VOID onWindowPosChanged(Event::WindowPosEvent& iEvent);

  //! Occurs before the window position or order has changed
  //! pWindowPos:      pointer to a WINDOWPOS structure
  virtual VOID onWindowPosChanging(Event::WindowPosEvent& iEvent);

  //! Occurs after the window was moved
  //! x:               x coordinate of the window
  //! y:               y coordinate of the window
  virtual VOID onMove(Event::MoveEvent& iEvent);

  //! Occurs when the window is being moved
  //! pRect:           pointer to a RECT structure
  virtual VOID onMoving(Event::MovingEvent& iEvent);

  //! Occurs after the window was resized
  //! nSizeType:       the type of resizing requested (any SIZE_* value)
  //! width:           the new width of the window
  //! height:          the new height of the window
  virtual VOID onSize(Event::SizeEvent& iEvent);

  //! Occurs when the window is being resized
  //! nSizeEdge:       the edge being sized (any WMSZ_* value)
  //! pRect:           pointer to a RECT structure
  virtual VOID onSizing(Event::SizingEvent& iEvent);

  //! Occurs when the window is enabled or disabled
  //! enabled:         the window has been enabled
  virtual VOID onEnable(Event::EnableEvent& iEvent);

  //! Occurs when the window is being closed
  virtual VOID onClose();

  //! Occurs when the window is being destroyed
  virtual VOID onDestroy();
#pragma endregion

#pragma region Drag & Drop Notifications
  //! Occurs when the drag enters, leaves or moves over the window
  //! (called after onDragEnter, onDragOver and onDragLeave)
  virtual HRESULT onGiveFeedback(Event::DragFeedbackEvent& iEvent);

  //! Occurs when a key or mouse button is pressed during the drag
  //! specifies if the drag can continue or is canceled
  virtual HRESULT onQueryContinueDrag(Event::QueryContinueDragEvent& iEvent);

  //! Occurs when the drag enters the window
  //! specifies if the drag is accepted and its effects
  virtual HRESULT onDragEnter(Event::DragObjectEvent& iEvent);

  //! Occurs when the drag moves over the window
  virtual HRESULT onDragOver(Event::DragEvent& iEvent);

  //! Occurs when the drag leaves the window
  virtual HRESULT onDragLeave();

  //! Occurs when a drag drop is performed on the window
  virtual HRESULT onDrop(Event::DragObjectEvent& iEvent);
#pragma endregion

public:
#pragma region Constructors & Destructors
  //! Frame window constructor
  SPLINL FrameWnd()
  {
    mDropTarget = NULL;
    mIsMouseOver  = FALSE;
    mModal       = FALSE;
    mResult      = DialogCancel;
  }
#pragma endregion

#pragma region Management
  //! Shows window modally (returns when hidden)
  DialogResult  showModal();
  //! Simulates a button press
  VOID          doClick(UINT uID);
#pragma endregion

#pragma region Accessors
  //! (Un)registers window as a drag drop target
  BOOL  setIsDropTarget(BOOL fTarget);

  //! Checks if mouse is over window
  SPLINL BOOL   isMouseOver()
  {
    return mIsMouseOver;
  }
  //! Gets window modal state
  SPLINL BOOL   isModal()
  {
    return mModal;
  }
  //! Gets window result
  SPLINL DialogResult getResult()
  {
    return mResult;
  }
  //! Sets window result
  SPLINL VOID   setResult(DialogResult value)
  {
    mResult = value;
  }

  //! Gets next child window
  HWND  getNextChild(HWND start, BOOL previous);
#pragma endregion

#pragma region Friends
  friend class Dialog;
  friend class Window;
  friend class HiddenWnd;
#pragma endregion
};

#endif